#ifndef __CORE_MATRIX3__
#define __CORE_MATRIX3__
#include "CoreDefine.h"
#include "Vector3.h"
namespace Core
{
	class rtMatrix2;
	class rtMatrix4;
	class rtQuaternions;
	class rtAngles;
	class rtRotation;

	class rtMatrix3
	{
	public:
		rtMatrix3(void);
		explicit rtMatrix3(const rtVector3& x, const rtVector3& y, const rtVector3& z);
		explicit rtMatrix3(const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz);
		explicit rtMatrix3(const float src[3][3]);

		static rtMatrix3 mat3_zero;
		static rtMatrix3 mat3_identity;

		const rtVector3&	    operator [] (int index) const;
		rtVector3&		    operator [] (int index);
		rtMatrix3			operator - ()const;
		rtMatrix3			operator * (const float a) const;
		rtVector3			operator * (const rtVector3& vec) const;
		rtMatrix3			operator * (const rtMatrix3& a) const;
		rtMatrix3			operator + (const rtMatrix3& a) const;
		rtMatrix3			operator - (const rtMatrix3& a) const;
		rtMatrix3&		operator *= (const float a);
		rtMatrix3&		operator *= (const rtMatrix3& a);
		rtMatrix3&		operator += (const rtMatrix3& a);
		rtMatrix3&		operator -= (const rtMatrix3& a);

		friend rtMatrix3	operator * (const float a, const rtMatrix3& mat3);
		friend rtVector3	operator * (const rtVector3& vec, const rtMatrix3& mat3);
		friend rtVector3&	operator *= (rtVector3& vec, const rtMatrix3& mat3);

		bool			compare(const rtMatrix3& a) const;
		bool			compare(const rtMatrix3&a, const float epsilon) const;
		bool			operator == (const rtMatrix3& a) const;
		bool			operator != (const rtMatrix3& a) const;

		void			zero(void);
		void			identity(void);
		bool			isIdentity(const float epsilon = MATRIX_EPSILON) const;
		bool			isSymmetric(const float epsilon = MATRIX_EPSILON) const;
		bool			isDiagonal(const float epsilon = MATRIX_EPSILON) const;
		bool			isRotated(void) const;

		void			projectVector(const rtVector3& src, rtVector3& dst) const;
		void			unprojectVector(const rtVector3& src, rtVector3& dst) const;

		bool			fixDegeneracies(void);
		bool			fixDenormals(void);

		float			trace(void) const;
		float			determinant(void) const;
		rtMatrix3		orthoNormalize(void) const;
		rtMatrix3&		orthoNormalizeSelf(void);
		rtMatrix3		transpose(void) const;
		rtMatrix3&		transposeSelf(void);
		rtMatrix3		inverse(void) const;
		bool			inverseSelf(void);
		rtMatrix3		inverseFast(void) const;
		bool			inverseFastSelf(void);
		rtMatrix3		transposeMultiply(const rtMatrix3& b) const;

		rtMatrix3		inertiaTranslate(const float mass, const rtVector3& centerOfMass, const rtVector3& translation) const;
		rtMatrix3 &		inertiaTranslateSelf(const float mass, const rtVector3 &centerOfMass, const rtVector3& translation);
		rtMatrix3		inertiaRotate(const rtMatrix3& rotation) const;
		rtMatrix3 &		inertiaRotateSelf(const rtMatrix3& rotation);

		int				getDimension(void) const;

		rtAngles		toAngles(void) const;
		rtQuaternions	toQuat(void) const;
		rtRotation		toRotation(void) const;
		rtMatrix4		toMat4(void) const;
		rtVector3		toAngularVelocity(void) const;
		const float *	toFloatPtr(void) const;
		float *			toFloatPtr(void);

		friend void		    transposeMultiply(const rtMatrix3& inv, const rtMatrix3& b, rtMatrix3& dst);
		friend rtMatrix3	skewSymmetric(rtVector3 const& src);

	private:
		rtVector3			m_Mat[3];
	};


}
#endif


